<script setup lang="ts">
import { computed, ref, unref, watch } from 'vue'
import {
  ArrowLeft,
  ArrowRight,
  Delete,
  Document,
  Download,
  Plus,
  ZoomIn
} from '@element-plus/icons-vue'
import { useBaseFileApi } from '@/api/base'
import { swapArrayElements } from '@/utils'
import type { BusinessUIFile } from '@/types/custom'

interface Props {
  title?: string
  disabled?: boolean
  hideTitle?: boolean
}

const modelValue = defineModel<BusinessUIFile[] | undefined>()

const props = defineProps<Props>()

const emit = defineEmits(['input'])

const { GetBaseFileDown } = useBaseFileApi()

const dialogVisible = ref(false)
const dialogImageIndex = ref()
const formImages = ref<BusinessUIFile[]>([])

// 顶部工具栏-下载
const handleDownload = (file: BusinessUIFile) => {
  if (file.id) {
    GetBaseFileDown(file.id).then((data: any) => {
      const objectUrl = URL.createObjectURL(data)
      let link = document.createElement('a')
      link.style.display = 'none'
      link.href = objectUrl
      link.setAttribute('download', file.fileName)
      document.body.appendChild(link)
      link.click()
      URL.revokeObjectURL(objectUrl) // 释放内存
    })
  }
}

const isIdentical = (v: BusinessUIFile, b: BusinessUIFile) => {
  return v.uid === b.uid || (v.id && v.id === b.id)
}

/**
 * 删除
 */
const handleRemove = (file: BusinessUIFile) => {
  const index = unref(formImages).findIndex((f) => isIdentical(f, file))
  if (index >= 0) formImages.value.splice(index, 1)
}

/**
 * 删除
 */
const handlePreview = (file: BusinessUIFile) => {
  const images = unref(formImages)
  dialogImageIndex.value = images.findIndex((f) => f.url === file.url)
  dialogVisible.value = true
}

const handleClosePreview = () => {
  dialogVisible.value = false
}

const handleSwitch = (file: BusinessUIFile, choice: -1 | 1) => {
  const images = unref(formImages)
  const index = images.findIndex((f) => isIdentical(f, file))
  const idx = index + choice
  if (index >= 0 && images[idx]) swapArrayElements(images, index, idx)
}

// 用于阻断双向监听
let isFormImage = false

watch(
  formImages,
  () => {
    isFormImage = true
    const images = unref(formImages)
    modelValue.value = images.map((v) => {
      return {
        ...v,
        fileName: v.raw?.name || v.fileName,
        raw: v.raw
      }
    })
  },
  { deep: true }
)

watch(modelValue, () => {
  if (isFormImage) return (isFormImage = false)
  const list = unref(modelValue) || []
  list.sort((a, b) => {
    return (a.idx || 0) - (b.idx || 0)
  })
  formImages.value = list.map((v) => {
    v.url = v.imgThumbnailPath || v.path || v.url
    return v
  })
})

const isData = computed(() => {
  return !props.disabled || !!modelValue.value?.length
})
</script>

<template>
  <div v-if="isData" class="border-default base-radius">
    <div
      class="flex align-center justify-between border-solid title color-info"
      style="padding: 3px 5px"
      v-if="!hideTitle"
    >
      <div class="flex align-center">
        <el-icon>
          <Document />
        </el-icon>
        <span class="font14 ml5">{{ title || '图片列表' }}</span>
      </div>
    </div>
    <el-upload
      v-model:file-list="formImages"
      list-type="picture-card"
      :on-preview="handlePreview"
      :on-remove="handleRemove"
      :auto-upload="false"
      :disabled="disabled"
      multiple
      class="pa5"
    >
      <el-icon>
        <Plus />
      </el-icon>
      <template #file="{ file }">
        <div>
          <img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
          <div class="el-upload-list__item-actions">
            <div class="flex align-center justify-center flex-warp" style="gap: 5px">
              <span class="el-upload-list__item-preview" @click="handlePreview(file)">
                <el-icon><ZoomIn /></el-icon>
              </span>
              <span
                v-if="!disabled && file.id"
                class="el-upload-list__item-delete"
                @click="handleDownload(file)"
              >
                <el-icon><Download /></el-icon>
              </span>
              <span
                v-if="!disabled"
                class="el-upload-list__item-delete"
                @click="handleRemove(file)"
              >
                <el-icon><Delete /></el-icon>
              </span>
              <br />
              <span @click="handleSwitch(file, -1)">
                <el-icon><ArrowLeft /></el-icon>
              </span>
              <span @click="handleSwitch(file, 1)">
                <el-icon><ArrowRight /></el-icon>
              </span>
            </div>
          </div>
        </div>
      </template>
    </el-upload>
    <vxe-image-preview
      v-if="dialogVisible"
      v-model="dialogImageIndex"
      class="template-image-preview"
      :url-list="formImages.map((v) => v.path || v.imgThumbnailPath || v.url)"
      @close="handleClosePreview"
    ></vxe-image-preview>
  </div>
</template>
<style lang="scss" scoped>
.template-image-preview {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  top: 0;
  z-index: 3000;
  color: white;
  background-color: var(--el-bg-color);
}

.title {
  background-color: var(--el-fill-color-light);
}
</style>
